package com.example.myhl7project;

import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.v26.segment.MSH;
import ca.uhn.hl7v2.model.v26.segment.PID;
import ca.uhn.hl7v2.model.v26.segment.PV1;
import ca.uhn.hl7v2.model.v26.segment.OBR;
import ca.uhn.hl7v2.model.v26.segment.OBX;
import ca.uhn.hl7v2.util.Terser;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import ca.uhn.hl7v2.model.v26.message.ORU_R01;
@Service
public class HL7MessageService {
    private static final Logger logger = LoggerFactory.getLogger(HL7MessageService.class);

    // 宝莱特BHC编码系统标识
    private static final String BHC_SYSTEM = "BHC";

    public Message processMessage(Message message) throws Exception {
        if (!(message instanceof ca.uhn.hl7v2.model.v26.message.ORU_R01)) {
            throw new IllegalArgumentException("Unsupported message type: " + message.getClass().getName());
        }

        ORU_R01 oru = (ORU_R01) message;
        Terser terser = new Terser(message);

        MSH msh = oru.getMSH();
        String messageType = msh.getMessageType().getMessageCode().getValue();
        String controlId = msh.getMessageControlID().getValue();
        logger.info("🔄 接收 HL7 [{}], 类型 {}", controlId, messageType);

        // 解析 PID
        PID pid = oru.getPATIENT_RESULT().getPATIENT().getPID();
        String patientId = pid.getPatientIdentifierList(0).getIDNumber().getValue();
        String patientName = pid.getPatientName(0).getGivenName().getValue();
        String birthDate = extractTimePart(pid.getDateTimeOfBirth().getValue());
        String gender = pid.getAdministrativeSex().getValue();

        logger.info("🧍 Patient: {} - {} ({})", patientId, patientName, gender);

        // 解析 PV1（安全方式）
        try {
            PV1 pv1 = oru.getPATIENT_RESULT().getPATIENT().getVISIT().getPV1();
            if (pv1 != null && pv1.getPatientClass().getValue() != null) {
                String patientClass = pv1.getPatientClass().getValue();
                String location = pv1.getAssignedPatientLocation().getPointOfCare().getValue();
                String doctor = pv1.getAttendingDoctor(0).getIDNumber().getValue();

                logger.info("🏥 就诊类型: {}, 科室: {}, 医生: {}", patientClass, location, doctor);
            }
        } catch (Exception e) {
            logger.warn("⚠️ HL7 消息中未包含有效的 PV1 段或解析失败：{}", e.getMessage());
        }

        // 解析 OBR
        OBR obr = oru.getPATIENT_RESULT().getORDER_OBSERVATION().getOBR();
        String observationDateTimeStr = obr.getObservationDateTime().getValue();
        String observationTime = extractTimePart(observationDateTimeStr);

        // OBX 多段
        OBX[] obxList = oru.getPATIENT_RESULT().getORDER_OBSERVATION().getOBSERVATIONAll().stream()
                .map(obs -> {
                    try {
                        return obs.getOBX();
                    } catch (Exception e) {
                        return null;
                    }
                })
                .filter(java.util.Objects::nonNull)
                .toArray(OBX[]::new);

        for (OBX obx : obxList) {
            processOBXSegment(obx, terser);
        }

        return message;
    }

    private List<OBX> getAllOBXSegments(Message message) {
        List<OBX> obxList = new ArrayList<>();
        try {
            String segmentName = "OBX";
            int index = 0;
            while (true) {
                OBX obx = (OBX) message.get("OBX", index);
                if (obx == null) break;
                obxList.add(obx);
                index++;
            }
        } catch (Exception e) {
            // 正常：超过时会抛异常
        }
        return obxList;
    }

    private void processOBXSegment(OBX obx, Terser terser) {
        try {
            String valueType = obx.getValueType().getValue();
            String observationId = obx.getObservationIdentifier().getIdentifier().getValue();
            String codingSystem = obx.getObservationIdentifier().getNameOfCodingSystem().getValue();
            String subId = obx.getObservationSubID().getValue();
            String observationValue = obx.getObservationValue(0).getData().toString();
            String status = obx.getObservationResultStatus().getValue();

            // 宝莱特特定处理
            if (BHC_SYSTEM.equals(codingSystem)) {
                // 模块上线消息 (5^^BHC)
                if ("5".equals(observationId)) {
                    logger.info("Module online: {}", observationValue);
                }
                // 支持的参数 (7^^BHC)
                else if ("7".equals(observationId)) {
                    logger.info("Supported parameter: {} for module {}", observationValue, subId);
                }
                // 参数值 (NM类型)
                else if ("NM".equals(valueType)) {
                    String userDefined = obx.getUserDefinedAccessChecks().getValue();
                    String obsDateTimeStr = obx.getDateTimeOfTheObservation().getValue();
                    String obsTime = extractTimePart(obsDateTimeStr);

                    if ("APERIODIC".equals(userDefined)) {
                        logger.info("Aperiodic measurement [{}]: {} at {}",
                                observationId, observationValue, obsTime);
                    } else {
                        logger.info("Parameter value [{}]: {}", observationId, observationValue);
                    }
                }
                // 报警信息
                else if ("CE".equals(valueType)) {
                    String dtmValue = obx.getDateTimeOfTheObservation().getValue();
                    String alarmTime = extractTimePart(dtmValue);
                    logger.warn("Alarm [{}]: {} at {}",
                            observationId, observationValue, alarmTime);
                }
                // 系统参数
                else if ("ST".equals(valueType) || "CE".equals(valueType)) {
                    logger.info("System parameter [{}]: {}", observationId, observationValue);
                }
            }
        } catch (Exception e) {
            logger.error("Error processing OBX segment", e);
        }
    }

    private String extractDatePart(String dtmValue) {
        if (dtmValue == null || dtmValue.length() < 8) return dtmValue;
        return dtmValue.substring(0, 8);  // YYYYMMDD
    }

    private String extractTimePart(String dtmValue) {
        if (dtmValue == null || dtmValue.length() < 8) return dtmValue;

        int endIndex = Math.min(dtmValue.length(), 14);
        String timePart = dtmValue.substring(8, endIndex);

        StringBuilder formatted = new StringBuilder(timePart);
        while (formatted.length() < 6) {
            formatted.append("0");
        }

        return formatted.substring(0, 2) + ":" +
                formatted.substring(2, 4) + ":" +
                formatted.substring(4, 6);
    }
}
